#pragma once 
#include "Cond.hpp"
#include "Mutex.hpp"
#include <queue>
namespace BlockQueueModule
{
    using namespace MyCondModule;
    using namespace MyMutexModule;
    //这个模版类可能接收的就是任务了
    const int CAP = 10; //默认10个货架位置
    template<class T>
    class BlockQueue
    {
    public:
        BlockQueue(int cap = CAP)
            :_pcount(0),_count(0),_cap(cap)
        {

        }

        bool Isfull(){
            return _bq.size() == _cap;
        }
        bool IsEmpty(){return _bq.empty();}
        //生产者放数据
        void Enqueue(T& data){
            {
                LockGuard lock(_mutex);
                while(Isfull()){
                    //满了就不能放
                    _pcount++; //生产者阻塞数目+1
                    cout << "生产者陷入阻塞" << endl;
                    _productor.Wait(_mutex); //去条件变量中等待
                    cout << "生产者从阻塞中出来" << endl;
                    _pcount--;
                }
                _bq.push(data); //放入数据
                if(_count){ //如果有消费者再等待
                    _consumer.NotifyAll();
                }
            }   
        }
        void Pop(T* data){
            {
                LockGuard lock(_mutex);
                while(IsEmpty()){
                    //空了就让消费者陷入等待
                    _count++;
                    cout << "消费者陷入等待" << endl;
                    _consumer.Wait(_mutex);
                    cout << "消费者从等待中出来" << endl;
                    _count--;
                }
                *data = _bq.front();
                _bq.pop();
                if (_pcount){ //如果有生产者在等待
                    // _productor.NotifySignal();
                    _productor.NotifyAll();
                }
            }
        }
        ~BlockQueue(){}
    private:
        int _cap;
        queue<T> _bq;
        Mutex _mutex;
        Cond _productor;
        Cond _consumer;
        int _pcount; //生产者阻塞数量
        int _count; //消费者阻塞数量
    };
}